﻿using System;
using System.Collections.Generic;
using System.Text;
using Pixysoft.Framework.XSchEmA.Entity;
using System.Data;

namespace Pixysoft.Framework.Noebe.Tools
{
    /// <summary>
    /// 创建测试数据
    /// </summary>
    class NoebeDemoDataCreator : INoebeDemoDataCreator
    {
        int maxRows = 100;

        double millionsago = 1000 * 60 * 60 * 24 * 7;// 7 days

        DateTime timefrom = DateTime.MinValue;

        double timestep = -1;

        private NoebeDemoDataCreator()
        {
        }

        public NoebeDemoDataCreator(int dayago, int maxrows)
        {
            this.maxRows = maxrows;

            this.millionsago = dayago * 24 * 60 * 60 * 1000;

            this.timestep = millionsago / maxRows;

            this.timefrom = DateTime.Now.AddMilliseconds(-1 * millionsago);
        }

        public void CreateDemoData(NoebeConfiguration config)
        {
            //reset time

            NoebeManager.Reload(config);

            DatabaseSchema database = NoebeManager.Instance.GetSchema();

            NoebeManager.Instance.GetAssembly().Schema.TransformToGeneral(database);

            DataSet ds = new DataSet();

            List<string> donelist = new List<string>();

            foreach (TableSchema table in database.Tables)
            {
                CreateDemoData(database, table, ds, donelist);
            }


        }

        private void CreateDemoData(DatabaseSchema database, TableSchema table, DataSet ds, List<string> donelist)
        {
            if (donelist.Contains(table.TableName))
                return;

            donelist.Add(table.TableName);

            foreach (ForeignKeySchema fk in database.GetForeignKeys(table))
            {
                this.CreateDemoData(database, fk.PkTable, ds, donelist);
            }

            ds.Tables.Add(CreateDemoData(database, table, ds));
        }

        private DataTable CreateDemoData(DatabaseSchema database, TableSchema schema, DataSet ds)
        {
            this.timefrom = DateTime.Now.AddMilliseconds(-1 * millionsago);

            DataTable table = NoebeManager.Instance.GetEntity(schema.TableName);

            for (int i = 0; i < maxRows; i++)
            {
                DataRow row = table.NewRow();

                foreach (ColumnSchema colschema in schema.Columns)
                {
                    List<ForeignKeySchema> fks = database.GetForeignKeys(colschema);

                    if (fks.Count > 0)
                    {
                        foreach (ForeignKeySchema fk in fks)
                        {
                            if (fk.PkTableName == schema.TableName)
                            {
                                row[colschema.ColumnName] = row[fk.PkColumnNames[fk.FkColumnNames.IndexOf(colschema.ColumnName)]];

                                break;
                            }

                            if (!ds.Tables.Contains(fk.PkTableName))
                            {
                                throw new Exception("mising foreignkey table in ds.");
                            }


                            DataTable fktable = ds.Tables[fk.PkTableName];

                            row[colschema.ColumnName] = fktable.Rows[i][fk.PkColumnNames[fk.FkColumnNames.IndexOf(colschema.ColumnName)]];

                            break;
                        }
                    }
                    else
                    {
                        //针对主键、唯一等 需要生成独特的序列

                        switch (Pixysoft.EnumCoder.ToEnum<DotNetDataType>(colschema.DataType.DataType))
                        {
                            case DotNetDataType.Boolean:
                                {
                                    row[colschema.ColumnName] = new Random(DateTime.Now.Millisecond).Next(1) == 1 ? true : false;

                                    break;
                                }
                            case DotNetDataType.Char:
                            case DotNetDataType.Decimal:
                            case DotNetDataType.Double:
                            case DotNetDataType.Int32:
                            case DotNetDataType.Int64:
                            case DotNetDataType.Single:
                                {
                                    row[colschema.ColumnName] = i;

                                    break;
                                }
                            case DotNetDataType.String:
                                {
                                    string columnValue = i.ToString() + Pixysoft.Security.Random.Instance.GetRandomString(30);

                                    row[colschema.ColumnName] = colschema.DataType.Length > 0 ? columnValue.Substring(0, (int)colschema.DataType.Length) : columnValue;

                                    break;
                                }
                            case DotNetDataType.DateTime:
                                {
                                    row[colschema.ColumnName] = timefrom;

                                    this.timefrom = timefrom.AddMilliseconds(timestep);

                                    break;
                                }
                            case DotNetDataType.Byte:
                                {
                                    row[colschema.ColumnName] = StringCoder.StringToByte(Pixysoft.Security.Random.Instance.GetRandomString(100));

                                    break;
                                }
                        }
                    }
                }

                table.Rows.Add(row);
            }

            NoebeManager.Instance.Session.Insert(table);

            return table;
        }
    }
}
